/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：呼叫中心-网关层
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taiping.cc.gateway.filters;

import com.taipingframework.utility.constant.ApplicationConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Component
public class ResponseHeaderFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        final String requestId = exchange.getAttribute(ApplicationConstant.RESPONSE_IDENTITY);

        log.info("网关过滤器 - Web请求（{}）开始", requestId);
        return chain.filter(exchange)
                .doOnSuccess((voidMono) -> {
                    // 重写响应头
                    ServerHttpResponse response = exchange.getResponse();
                    HttpHeaders headers = response.getHeaders();
                    // 经过调试发现，非正常返回时对象`headers`的类型为org.springframework.http.ReadOnlyHttpHeaders
                    // 此时若修改响应头将引发二次异常！
                    if (!HttpHeaders.class.equals(headers.getClass())) {
                        log.warn("网关过滤器 - Web请求（{}）结束，响应头是只读的，不允许重写", requestId);
                        return;
                    }

                    // 在HTTP请求的响应头中记录requestId
                    headers.add(ApplicationConstant.RESPONSE_IDENTITY, requestId);
                    log.info("Web请求（{}）新增响应头`{}`值为`{}`", requestId, ApplicationConstant.RESPONSE_IDENTITY, requestId);
                    // 防止重复添加相同的Key
                    Set<String> keySet = headers.keySet();
                    for (String k : keySet) {
                        List<String> v = headers.get(k);
                        if (null != v && v.size() > 1) {
                            List<String> list = v.stream().distinct().collect(Collectors.toList());
                            headers.replace(k, list);
                            log.info("Web请求（{}）在结束时替换`值`重复的响应头`{}`", requestId, k);
                        }
                    }

                })
                .doOnTerminate(() -> log.info("网关过滤器 - Web请求（{}）结束", requestId));
    }

//CHECKSTYLE:OFF

    @Override
    public int getOrder() {
        return 0;
    }

//CHECKSTYLE:ON
}
